package com.san.common.datasource;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.san.common.utils.AESUtils;
import com.san.common.utils.Constant;
import com.san.metadata.domain.DataSourceDO;
import com.san.metadata.service.DataSourceService;

@Service
public class JdbcConnectionPool {

	/**
	 * Oracle驱动
	 */
	private static final String DIVER_ORACLE = "oracle.jdbc.driver.OracleDriver";

	/**
	 * MySQL驱动
	 */
	private static final String DIVER_MYSQL = "com.mysql.jdbc.Driver";

	@Autowired
	DataSourceService dataSourceService;

	@Value("${spring.datasource.initialSize}")
	private int initialSize;

	@Value("${spring.datasource.minIdle}")
	private int minIdle;

	@Value("${spring.datasource.maxActive}")
	private int maxActive;

	@Value("${spring.datasource.maxWait}")
	private int maxWait;

	@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
	private int timeBetweenEvictionRunsMillis;

	@Value("${spring.datasource.minEvictableIdleTimeMillis}")
	private int minEvictableIdleTimeMillis;

	@Value("${spring.datasource.validationQuery}")
	private String validationQuery;

	@Value("${spring.datasource.testWhileIdle}")
	private boolean testWhileIdle;

	@Value("${spring.datasource.testOnBorrow}")
	private boolean testOnBorrow;

	@Value("${spring.datasource.testOnReturn}")
	private boolean testOnReturn;

	@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
	private int maxPoolPreparedStatementPerConnectionSize;

	@Value("${spring.datasource.filters}")
	private String filters;

	@Value("{spring.datasource.connectionProperties}")
	private String connectionProperties;

	Map<String, DruidDataSource> dbMap = new HashMap<String, DruidDataSource>();

	@PostConstruct
	public void init() {
		refreshDataSource();
	}

	public void refreshDataSource() {
		try {
			DruidDataSource druidDataSource = null;
			List<DataSourceDO> list = dataSourceService.getAllSource();
			for (DataSourceDO dataSourceDO : list) {
				druidDataSource = new DruidDataSource();
				// 设置连接参数
				String url = "";
				String className = "";
				boolean poolPreparedStatements = false;
				switch (dataSourceDO.getSourceType()) {
				case Constant.SOURCE_TYPE_ORACLE:
					className = DIVER_ORACLE;
					url = "jdbc:oracle:thin:@" + dataSourceDO.getIpAddress() + ":" + dataSourceDO.getPort() + ":"
							+ dataSourceDO.getDbName();
					poolPreparedStatements = true;
					break;
				case Constant.SOURCE_TYPE_MYSQL:
					className = DIVER_MYSQL;
					url = "jdbc:mysql://" + dataSourceDO.getIpAddress() + ":" + dataSourceDO.getPort() + "/"
							+ dataSourceDO.getDbName()
							+ "?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true&rewriteBatchedStatements=true&autoReconnect=true&useSSL=false";
					break;
				default:
					break;
				}
				druidDataSource.setUrl(url);
				druidDataSource.setDriverClassName(className);
				druidDataSource.setUsername(dataSourceDO.getDbUser());
				druidDataSource.setPassword(AESUtils.AESDecode(Constant.DATA_SOURCE_KEY, dataSourceDO.getDbPassword()));

				// 配置初始化大小、最小、最大
				druidDataSource.setInitialSize(initialSize);
				druidDataSource.setMinIdle(minIdle);
				druidDataSource.setMaxActive(maxActive);
				// 配置获取连接等待超时的时间
				druidDataSource.setMaxWait(maxWait);
				druidDataSource.setTestWhileIdle(true);
				// 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
				druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
				druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
				// 防止过期
				druidDataSource.setValidationQuery("SELECT 1 from dual");
				// 连接泄漏监测
				druidDataSource.setRemoveAbandoned(false);
//				druidDataSource.setRemoveAbandonedTimeout(30);
				druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
				if (poolPreparedStatements) {
					druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
				}
				
				druidDataSource.setTestOnBorrow(true);
				druidDataSource.setFilters(filters);
				druidDataSource.setConnectionProperties(connectionProperties);

				dbMap.put(dataSourceDO.getSourceCode(), druidDataSource);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取数据源连接
	 * 
	 * @return
	 */
	public DruidPooledConnection getDBConnection(String dataSourceCode) throws Exception {
		DruidPooledConnection conn = null;
		DruidDataSource druidDataSource = dbMap.get(dataSourceCode);
		if (null != druidDataSource) {
			conn = druidDataSource.getConnection();
		}
		return conn;
	}

}
